#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cherrypy

from farado.logger import logger
from farado.ui.renderer import view_renderer
from farado.helpers.cookie_helper import current_session_id
from farado.general_manager_holder import project_manager, permission_manager
from farado.items.workflow import Workflow
from farado.items.state import State
from farado.items.edge import Edge
from farado.ui.operation_result import OperationResult
from farado.ui.base_view import BaseView, UiUserRestrictions
from farado.ui.base_view import bring_value, get_value, get_int_value, get_bool_value


class WorkflowsView(BaseView):

    #--------------------------------------------------------------------------#
    def __init__(self):
        super().__init__()
        self.name = '/workflows'

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def index(self):
        user = self.current_user()
        if not user:
            return self.login_and_open()

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа к перечню рабочих процессов."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        message = f"Открытие страницы с перечнем рабочих процессов."
        logger.info(f"%-18s | {message}", user.login)

        return view_renderer["workflows"].render(
            user=user,
            project_manager=project_manager(),
            operation_result=user.pop_last_action_result(),
            restriction=UiUserRestrictions(
                is_admin=is_admin,
            )
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def workflow(self, target_workflow_id=None, **args):
        user = self.current_user()
        if not user:
            if target_workflow_id:
                return self.login_and_open(f'/workflow/{target_workflow_id}', args)
            return self.login_and_open()

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа к рабочему процессу #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        args = bring_value(user.pop_last_action_data(), args)
        target_workflow_caption = get_value(args, 'target_workflow_caption', None)
        target_workflow_description = get_value(args, 'target_workflow_description', None)

        target_workflow = project_manager().workflow(target_workflow_id)

        operation_result = user.pop_last_action_result()
        if target_workflow_caption:
            if not target_workflow:
                target_workflow = Workflow()

                message = f"Создание рабочего процесса «{target_workflow_caption}»."
                logger.info(f"%-18s | {message}", user.login)

            target_workflow.caption = target_workflow_caption
            target_workflow.description = target_workflow_description
            project_manager().save_item(target_workflow)
            operation_result = OperationResult(
                caption="Рабочий процесс сохранён",
                kind="success"
            )
            target_workflow_id = target_workflow.id

            message = f"Рабочий процесс #{target_workflow_id} сохранён."
            logger.info(f"%-18s | {message}", user.login)

        message = f"Открытие страницы рабочего процесса #{target_workflow_id}."
        logger.info(f"%-18s | {message}", user.login)

        return view_renderer["workflow"].render(
            user=user,
            target_workflow=target_workflow,
            project_manager=project_manager(),
            operation_result=operation_result,
            restriction=UiUserRestrictions(
                is_admin=is_admin,
            )
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def add_workflow(self):
        user = self.current_user()
        if not user:
            return self.login_and_open('/add_workflow')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для создания рабочего процесса."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        message = f"Открытие страницы создания рабочего процесса."
        logger.info(f"%-18s | {message}", user.login)

        return view_renderer["workflow"].render(
            user=user,
            project_manager=project_manager(),
            target_workflow=None,
            save_result=None,
            restriction=UiUserRestrictions(
                is_admin=is_admin,
            )
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def remove_workflow(self, target_workflow_id):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/remove_workflow/{target_workflow_id}')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для удаления рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        project_manager().remove_item(Workflow, target_workflow_id)

        message = f"Рабочий процесс #{target_issue_kind_id} удалён."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Рабочий процесс удалён",
                kind="success"
            )
        )
        raise cherrypy.HTTPRedirect(cherrypy.url(f'/'))

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def add_state(self, target_workflow_id):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/add_state/{target_workflow_id}')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для создания состояния рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        state = State()
        state.workflow_id = int(target_workflow_id)
        state.caption = "New state"
        project_manager().save_item(state)

        message = f"Новое состояние добавлено рабочему процессу #{target_workflow_id}."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Состояние добавлено в рабочий процесс",
                kind="success",
                tab_name="states",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def save_state(self, target_workflow_id, **args):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/save_state/{target_workflow_id}', args)

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для изменения состояния рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        args = bring_value(user.pop_last_action_data(), args)
        target_state_id = get_int_value(args, 'target_state_id', None)
        target_state_caption = get_value(args, 'target_state_caption', None)
        target_state_description = get_value(args, 'target_state_description', None)
        target_state_weight = get_int_value(args, 'target_state_weight', 0)
        target_state_order = get_value(args, 'target_state_order', '')
        target_state_is_archive = get_bool_value(args, 'target_state_is_archive', 'on', False)

        target_state = project_manager().state(target_state_id)
        target_state.caption = target_state_caption
        target_state.description = target_state_description
        target_state.weight = target_state_weight
        target_state.order = target_state_order
        target_state.is_archive = target_state_is_archive

        project_manager().save_item(target_state)

        message = f"Состояние сохранено в рабочем процессе #{target_workflow_id}."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Состояние сохранено",
                kind="success",
                tab_name="states",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def remove_state(self, target_workflow_id, target_state_id):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/remove_state/{target_workflow_id}/{target_state_id}')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для удаления состояния #{target_state_id} рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        project_manager().remove_item(State, target_state_id)

        message = f"Состояние удалено из рабочего процесса #{target_workflow_id}."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Состояние удалено из рабочего процесса",
                kind="success",
                tab_name="states",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def add_edge(self, target_workflow_id):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/add_edge/{target_workflow_id}')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для создания перехода между состояниями рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        edge = Edge()
        edge.workflow_id = int(target_workflow_id)
        project_manager().save_item(edge)

        message = f"Добавлен переход между состояниями рабочего процесса #{target_workflow_id}."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Добавлен переход между состояниями рабочего процесса",
                kind="success",
                tab_name="edges",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def save_edge(self, target_workflow_id, **args):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/save_edge/{target_workflow_id}', args)

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для изменения перехода между состояниями рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        args = bring_value(user.pop_last_action_data(), args)
        target_edge_id = get_int_value(args, 'target_edge_id', None)
        target_edge_from_state_id = get_int_value(args, 'target_edge_from_state_id', None)
        target_edge_to_state_id = get_int_value(args, 'target_edge_to_state_id', None)

        target_edge = project_manager().edge(target_edge_id)
        target_edge.from_state_id = int(target_edge_from_state_id)
        target_edge.to_state_id = int(target_edge_to_state_id)
        project_manager().save_item(target_edge)

        message = f"Переход между состояниями рабочего процесса #{target_workflow_id} сохранён."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Переход между состояниями рабочего процесса сохранён",
                kind="success",
                tab_name="edges",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )

    #--------------------------------------------------------------------------#
    @cherrypy.expose
    def remove_edge(self, target_workflow_id, target_edge_id):
        user = self.current_user()
        if not user:
            return self.login_and_open(f'/remove_edge/{target_workflow_id}/{target_edge_id}')

        is_admin = self.is_admin(user.id)
        if not is_admin:
            message = f"Нет доступа для удаления перехода между состояниями рабочего процесса #{target_workflow_id}."
            logger.warn(f"%-18s | {message}", user.login)
            raise cherrypy.HTTPError(403, message)

        project_manager().remove_item(Edge, target_edge_id)

        message = f"Переход между состояниями рабочего процесса #{target_workflow_id} удалён."
        logger.info(f"%-18s | {message}", user.login)

        user.push_last_action_result(
            OperationResult(
                caption="Переход между состояниями рабочего процесса удалён",
                kind="success",
                tab_name="edges",
            )
        )
        raise cherrypy.HTTPRedirect(
            cherrypy.url(f'/workflow/{target_workflow_id}')
        )
